# _*_coding:utf-8 _*_
import traceback
# from loguru import logger
import time
# import datetime
import threading
import random
from datetime import datetime
import requests
import json
import urllib.parse

'''日志打印程序'''
'''

logger.add('./log/cdr_file_{time}.log', format="{time} {name} {level} {message}", level="INFO", rotation='10 MB',
           encoding='utf-8')  # 根据时间为日志命名，每10MB新建一个
'''

'''日期二次转码函数，有值转码，无值返回无值，以免报错'''


def dateurl(da):
    if da:
        return urllib.parse.unquote(da, 'utf-8')
    else:
        return da


'''话单写到cdrlog函数'''


def wcdr(fname, data):
    fn = 'cdrlog/' + fname + '.txt'
    with open(fn, 'w+') as zycdrt:
        zycdrt.write(str(data))
    print('错误cdr文件写入')


'''话单处理函数'''

'''sip外呼,就是分机直接拨打'''


def sipcall(ddj):
    try:
        # print(ddj)
        callerpro = ddj['cdr']['callflow']['caller_profile']
        dv = ddj['cdr']['variables']
        start_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('start_epoch'))))
        # dd2 = urllib.parse.unquote(dd, 'utf-8')  # 二进制转字符串解码url
        zysip = dv.get('zysip')
        lyid = zysip = dv.get('lyid', '')
        gwid = dv.get('gwid', '')
        aanswer_stamp = ''  # sip直拨无此值
        answer_stamp = dateurl(dv.get('answer_stamp'))  # 调用日期解码函数dateurl
        if str(answer_stamp) == 'None':
            answer_stamp = ''
        end_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('end_epoch'))))
        # print('endtime=', end_stamp, 'answer_stamp=', answer_stamp, 'starttime=', start_stamp)
        # print('aw2=', urllib.parse.unquote(answer_stamp, 'utf-8'))
        duration = dv.get('duration')
        usertime = 0
        call_uuid = dv.get('call_uuid')
        caller_id_number = callerpro.get('caller_id_number')
        trunk_number = dv.get('trunk_number')
        if str(trunk_number) == 'None':
            trunk_number = ''
        callee_id_number = callerpro.get('destination_number')
        queue = dv.get('zyqueue')
        agent = caller_id_number
        direction = dv.get('direction')
        calltype = dv.get('callType')
        outside_call = '外呼'
        appid = dv.get('appid')
        mydpj = dv.get('mydpj')
        digits_dialed = dv.get('digits_dialed')
        hangup_cause = dv.get('hangup_cause')
        hangup_disposition = dv.get('sip_hangup_disposition')
        if hangup_disposition == 'recv_bye':
            hangup_disposition = '客户'
        elif hangup_disposition == 'send_bye':
            hangup_disposition = '坐席'
        elif hangup_disposition == 'send_refuse':
            hangup_disposition = '拒绝'
        elif hangup_disposition == 'send_cancel':
            hangup_disposition = '取消'
        else:
            hangup_disposition = ''
        data1 = dv.get('data1')
        data2 = dv.get('data2')
        states = ''  # 要进行判断
        billsec = dv.get('billsec')  # 结束时间减去接听时间，通话时长，计算后得出多少秒
        record_session = ''
        rs1 = ddj['cdr']['app_log']['application']
        if rs1:
            for k in rs1:
                if k['@app_name'] == 'record_session':
                    rs2 = k['@app_data']
                    if rs2:
                        rs3 = rs2.split('/')
                        record_session = rs3[-1]

        if answer_stamp:
            states = '接听'
        else:
            states = '被叫未接'

        return {
            'starttime': start_stamp,
            'aanswer_stamp': aanswer_stamp,
            'answer_stamp': answer_stamp,
            'endtime': end_stamp,
            'totaltime': duration,
            'usertime': usertime,
            'callid': call_uuid,
            'caller': caller_id_number,
            'trunk_number': trunk_number,
            'called': callee_id_number,
            'queue': queue,
            'agent': agent,
            'direction': direction,
            'calltype': calltype,
            'type': outside_call,
            'filename': record_session,
            'appid': appid,
            'mydpj': mydpj,
            'digits_dialed': digits_dialed,
            'hangup_cause': hangup_cause,
            'hangup_disposition': hangup_disposition,
            'data1': data1,
            'data2': data2,
            'state': states,
            'billsec': billsec,
            'sip': zysip,
            'lyid': lyid,
            'gwid': gwid,
        }
    except Exception as e:
        print("处理来电cdr错误:")
        print(e)
        print(traceback.format_exc())
        # 名称时间戳，写到log
        fname = str(time.time())
        wcdr(fname, ddj)
        return 0


'''接口发起的外呼'''


def apitocall(ddj):
    try:
        # callerpro = ddj['cdr']['callflow']['caller_profile']
        dv = ddj['cdr']['variables']
        zysip = dv.get('zysip')
        start_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('start_epoch'))))
        # logger.error("start_stamp:" + start_stamp)

        aanswer_stamp = dateurl(dv.get('answer_stamp'))  # 接口外呼主叫先接听
        # logger.error("aanswer_stamp:" + aanswer_stamp)

        answer_stamp = dv.get('awbtime')
        if str(answer_stamp) == 'None':
            answer_stamp = ''
        # logger.error("answer_stamp:" + str(answer_stamp))

        end_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('end_epoch'))))
        # logger.error("end_stamp:" + end_stamp)
        # print('start_stamp=', start_stamp)
        # print('aanswer=', aanswer_stamp)
        # print('endtime=', end_stamp, 'awtime=', answer_stamp)
        duration = dv.get('duration')
        usertime = 0
        if aanswer_stamp:
            astart = datetime.strptime(aanswer_stamp, "%Y-%m-%d %H:%M:%S")
            aend = datetime.strptime(end_stamp, "%Y-%m-%d %H:%M:%S")
            atimes = (aend - astart).total_seconds()
            usertime = int(atimes)  # 主叫通话时长，结束时间减去主叫接听时间
        call_uuid = dv.get('call_uuid')
        caller_id_number = dv.get('caller')
        trunk_number = dv.get('trunk_number')
        if str(trunk_number) == 'None':
            trunk_number = ''
        callee_id_number = dv.get('called')
        queue = dv.get('zyqueue')
        agent = caller_id_number
        direction = dv.get('direction')
        calltype = dv.get('callType')
        outside_call = '外呼'
        appid = dv.get('appid')
        mydpj = dv.get('mydpj')
        digits_dialed = dv.get('digits_dialed')
        hangup_cause = dv.get('hangup_cause')
        hangup_disposition = dv.get('sip_hangup_disposition')
        if hangup_disposition == 'recv_bye':
            hangup_disposition = '客户'
        elif hangup_disposition == 'send_bye':
            hangup_disposition = '坐席'
        elif hangup_disposition == 'send_refuse':
            hangup_disposition = '拒绝'
        elif hangup_disposition == 'send_cancel':
            hangup_disposition = '取消'
        else:
            hangup_disposition = ''

        data1 = dv.get('data1')
        data2 = dv.get('data2')

        states = ''  # 要进行判断
        billsec = 0  # 结束时间减去接听时间，通话时长，计算后得出多少秒
        record_session = dv.get('recordSession')

        if answer_stamp:
            start = datetime.strptime(answer_stamp, "%Y-%m-%d %H:%M:%S")
            end = datetime.strptime(end_stamp, "%Y-%m-%d %H:%M:%S")
            btimes = (end - start).total_seconds()
            billsec = int(btimes)
            states = '接听'
        else:
            if aanswer_stamp:
                states = '被叫未接'
            else:
                states = '主叫未接'

        return {
            'starttime': start_stamp,
            'aanswer_stamp': aanswer_stamp,
            'answer_stamp': answer_stamp,
            'endtime': end_stamp,
            'totaltime': duration,
            'usertime': usertime,
            'callid': call_uuid,
            'caller': caller_id_number,
            'trunk_number': trunk_number,
            'called': callee_id_number,
            'queue': queue,
            'agent': agent,
            'direction': direction,
            'calltype': calltype,
            'type': outside_call,
            'filename': record_session,
            'appid': appid,
            'mydpj': mydpj,
            'digits_dialed': digits_dialed,
            'hangup_cause': hangup_cause,
            'hangup_disposition': hangup_disposition,
            'data1': data1,
            'data2': data2,
            'state': states,
            'billsec': billsec,
            'sip': zysip,
        }
    except Exception as e:
        print("处理来电cdr错误:")
        print(e)
        print(traceback.format_exc())
        # 名称时间戳，写到log
        fname = str(time.time())
        wcdr(fname, ddj)
        return 0



'''outdl批量外呼cdr'''


def outdl(ddj):
    try:
        # callerpro = ddj['cdr']['callflow']['caller_profile']
        dv = ddj['cdr']['variables']

        start_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('start_epoch'))))
        zysip = dv.get('zysip')
        if str(zysip) == 'None':
            zysip = ''
        aanswer_stamp = dv.get('aw')  # 来电无此值
        if str(aanswer_stamp) == 'None':
            aanswer_stamp = ''
        answer_stamp = dateurl(dv.get('cc_queue_answered'))  # url解码获取
        if str(answer_stamp) == 'None':
            answer_stamp = ''
        # logger.error("answer_stamp:"+str(answer_stamp))
        end_stamp = dv.get('end_epoch')
        # print('endtime=', end_stamp, 'awtime=', answer_stamp)
        duration = dv.get('duration')
        usertime = duration
        call_uuid = dv.get('call_uuid')
        caller_id_number = dv.get('zycaller')
        trunk_number = dv.get('trunk_number')
        if str(trunk_number) == 'None':
            trunk_number = ''
        callee_id_number = dv.get('callee_id_number')
        queue = dateurl(dv.get('zyqueue'))  # 获取值并url二次解码
        agent = dv.get('agent')
        direction = dv.get('direction')
        calltype = dv.get('callType')
        if str(calltype) == 'None':
            calltype = ''
        outside_call = '来电'
        record_session = dv.get('recordSession')
        appid = dv.get('appid')
        mydpj = dv.get('mydpj')
        if str(mydpj) == 'None':
            mydpj = ''
        digits_dialed = dv.get('digits_dialed')
        if str(digits_dialed) == 'none':
            digits_dialed = ''
        hangup_cause = dv.get('hangup_cause')
        hangup_disposition = dv.get('sip_hangup_disposition')
        data1 = dv.get('data1')
        data2 = dv.get('data2')
        states = ''  # 要进行判断
        wait_time = 0  # 接听时间减去转接时间，来电振铃时长
        billsec = 0  # 结束时间减去接听时间，通话时长，计算后得出多少秒
        cc_queue_joined = dateurl(dv.get('cc_queue_joined'))  # 进入队列时间
        # logger.error("cc_queue_joined:" + str(cc_queue_joined))
        tagtime = dateurl(dv.get('tagtime'))  # 转接坐席时间
        # logger.error("tagtime:" + str(tagtime))
        yichu = dv.get('yichu')

        if answer_stamp:
            antc = int(time.mktime(time.strptime(answer_stamp, '%Y-%m-%d %H:%M:%S')))
            tac = int(time.mktime(time.strptime(tagtime, '%Y-%m-%d %H:%M:%S')))
            billsec = int(int(end_stamp) - antc)  # 结束时间减去接听时间
            states = '接听'
            wait_time = int(antc - tac)  # 接听时间减去转接时间

        else:
            if cc_queue_joined:
                if yichu:
                    states = '队列超时'
                else:
                    states = '队列放弃'
            else:
                states = 'ivr'

        end_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(end_stamp)))


        return {
            'starttime': start_stamp,
            'aanswer_stamp': aanswer_stamp,
            'answer_stamp': answer_stamp,
            'endtime': end_stamp,
            'totaltime': duration,
            'usertime': usertime,
            'callid': call_uuid,
            'caller': caller_id_number,
            'trunk_number': trunk_number,
            'called': callee_id_number,
            'queue': queue,
            'agent': agent,
            'direction': direction,
            'calltype': calltype,
            'type': outside_call,
            'filename': record_session,
            'appid': appid,
            'mydpj': mydpj,
            'digits_dialed': digits_dialed,
            'hangup_cause': hangup_cause,
            'hangup_disposition': hangup_disposition,
            'data1': data1,
            'data2': data2,
            'state': states,
            'waittime': wait_time,
            'billsec': billsec,
            'sip': zysip,
            'inqueuetime': cc_queue_joined,
            'toagnettime': tagtime,

        }
    except Exception as e:
        print("处理来电cdr错误:")
        print(e)
        print(traceback.format_exc())
        # 名称时间戳，写到log
        fname = str(time.time())
        wcdr(fname, ddj)
        return 0








'''外线来电cdr'''


def incall(ddj):
    try:
        # callerpro = ddj['cdr']['callflow']['caller_profile']
        dv = ddj['cdr']['variables']

        start_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('start_epoch'))))
        zysip = dv.get('zysip')
        if str(zysip) == 'None':
            zysip = ''
        aanswer_stamp = dv.get('aw')  # 来电无此值
        if str(aanswer_stamp) == 'None':
            aanswer_stamp = ''
        answer_stamp = dateurl(dv.get('cc_queue_answered'))  # url解码获取
        if str(answer_stamp) == 'None':
            answer_stamp = ''
        # logger.error("answer_stamp:"+str(answer_stamp))
        end_stamp = dv.get('end_epoch')
        # print('endtime=', end_stamp, 'awtime=', answer_stamp)
        duration = dv.get('duration')
        usertime = duration
        call_uuid = dv.get('call_uuid')
        caller_id_number = dv.get('zycaller')
        trunk_number = dv.get('trunk_number')
        if str(trunk_number) == 'None':
            trunk_number = ''
        callee_id_number = dv.get('callee_id_number')
        queue = dateurl(dv.get('zyqueue'))  # 获取值并url二次解码
        agent = dv.get('agent')
        direction = dv.get('direction')
        calltype = dv.get('callType')
        if str(calltype) == 'None':
            calltype = ''
        outside_call = '来电'
        record_session = dv.get('recordSession')
        appid = dv.get('appid')
        mydpj = dv.get('mydpj')
        if str(mydpj) == 'None':
            mydpj = ''
        digits_dialed = dv.get('digits_dialed')
        if str(digits_dialed) == 'none':
            digits_dialed = ''
        hangup_cause = dv.get('hangup_cause')
        hangup_disposition = dv.get('sip_hangup_disposition')
        data1 = dv.get('data1')
        data2 = dv.get('data2')
        states = ''  # 要进行判断
        wait_time = 0  # 接听时间减去转接时间，来电振铃时长
        billsec = 0  # 结束时间减去接听时间，通话时长，计算后得出多少秒
        cc_queue_joined = dateurl(dv.get('cc_queue_joined'))  # 进入队列时间
        # logger.error("cc_queue_joined:" + str(cc_queue_joined))
        tagtime = dateurl(dv.get('tagtime'))  # 转接坐席时间
        # logger.error("tagtime:" + str(tagtime))
        yichu = dv.get('yichu')

        if answer_stamp:
            antc = int(time.mktime(time.strptime(answer_stamp, '%Y-%m-%d %H:%M:%S')))
            tac = int(time.mktime(time.strptime(tagtime, '%Y-%m-%d %H:%M:%S')))
            billsec = int(int(end_stamp) - antc)  # 结束时间减去接听时间
            states = '接听'
            wait_time = int(antc - tac)  # 接听时间减去转接时间

        else:
            if cc_queue_joined:
                if yichu:
                    states = '队列超时'
                else:
                    states = '队列放弃'
            else:
                states = 'ivr'

        end_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(end_stamp)))


        return {
            'starttime': start_stamp,
            'aanswer_stamp': aanswer_stamp,
            'answer_stamp': answer_stamp,
            'endtime': end_stamp,
            'totaltime': duration,
            'usertime': usertime,
            'callid': call_uuid,
            'caller': caller_id_number,
            'trunk_number': trunk_number,
            'called': callee_id_number,
            'queue': queue,
            'agent': agent,
            'direction': direction,
            'calltype': calltype,
            'type': outside_call,
            'filename': record_session,
            'appid': appid,
            'mydpj': mydpj,
            'digits_dialed': digits_dialed,
            'hangup_cause': hangup_cause,
            'hangup_disposition': hangup_disposition,
            'data1': data1,
            'data2': data2,
            'state': states,
            'waittime': wait_time,
            'billsec': billsec,
            'sip': zysip,
            'inqueuetime': cc_queue_joined,
            'toagnettime': tagtime,

        }
    except Exception as e:
        print("处理来电cdr错误:")
        print(e)
        print(traceback.format_exc())
        # 名称时间戳，写到log
        fname = str(time.time())
        wcdr(fname, ddj)
        return 0


'''振铃未接cdr'''


def inzl(ddj):
    try:
        callerpro = ddj['cdr']['callflow']['caller_profile']
        dv = ddj['cdr']['variables']

        start_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('start_epoch'))))
        # logger.error("start_stamp:" + str(start_stamp))
        zysip = dv.get('zysip')
        if str(zysip) == 'None':
            zysip = ''
        aanswer_stamp = ''  # 来电无此值
        answer_stamp = ''
        end_stamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(dv.get('end_epoch'))))
        print("end_stamp:" + str(end_stamp))
        duration = dv.get('duration')
        usertime = 0
        call_uuid = dv.get('call_uuid')
        uuida = dv.get('uuida')  # 来电主话单id，可进行关联
        caller_id_number = callerpro.get('caller_id_number')
        trunk_number = dv.get('trunk_number')
        callee_id_number = callerpro.get('callee_id_number')
        queue = dateurl(dv.get('queueb'))  # 获取值并url二次解码
        agent = callee_id_number
        direction = dv.get('direction')
        calltype = dv.get('callType')
        if str(calltype) == 'None':
            calltype = ''
        outside_call = '来电'
        record_session = dv.get('recordSession')
        appid = dv.get('appid')
        mydpj = dv.get('mydpj')
        if str(mydpj) == 'None':
            mydpj = ''
        digits_dialed = dv.get('digits_dialed')
        if str(digits_dialed) == 'none':
            digits_dialed = ''
        hangup_cause = dv.get('hangup_cause')
        hangup_disposition = dv.get('sip_hangup_disposition')
        data1 = dv.get('data1')
        data2 = dv.get('data2')
        states = '振铃未接'  # 要进行判断
        wait_time = duration  # 接听时间减去转接时间
        billsec = 0  # 结束时间减去接听时间，通话时长，计算后得出多少秒
        cc_queue_joined = dv.get('cc_queue_joined')
        # logger.error("cc_queue_joined:" + str(cc_queue_joined))
        tagtime = dateurl(dv.get('tagtime'))  # url解码获取
        # logger.error("tagtime:" + str(tagtime))
        yichu = dv.get('yichu')

        return {
            'starttime': start_stamp,
            'aanswer_stamp': aanswer_stamp,
            'answer_stamp': answer_stamp,
            'endtime': end_stamp,
            'totaltime': duration,
            'usertime': usertime,
            'callid': call_uuid,
            'caller': caller_id_number,
            'trunk_number': trunk_number,
            'called': callee_id_number,
            'queue': queue,
            'agent': agent,
            'direction': direction,
            'calltype': calltype,
            'type': outside_call,
            'filename': record_session,
            'appid': appid,
            'mydpj': mydpj,
            'digits_dialed': digits_dialed,
            'hangup_cause': hangup_cause,
            'hangup_disposition': hangup_disposition,
            'data1': data1,
            'data2': data2,
            'state': states,
            'billsec': billsec,
            'sip': zysip,
            'uuida': uuida
        }
    except Exception as e:
        print("处理来电cdr错误:")
        print(e)
        print(traceback.format_exc())
        # 名称时间戳，写到log
        fname = str(time.time())
        wcdr(fname, ddj)
        return 0


'''postcdr-url'''

# url1 = 'http://192.168.31.142:58080/api/cdrcs/'

'''推送话单请求'''


def postcdr(data):
    try:
        url = data.get('cdrurl')
        if url:

            aheaders = {'Content-Type': 'application/json'}
            rp = requests.post(url, data=json.dumps(data), headers=aheaders, timeout=10)  # 第一次推话单
            if rp:
                if rp.status_code == 200:
                    print('话单已推送=', data)
                else:
                    time.sleep(5)
                    print('话单重推开始')
                    rp = requests.post(url, data=json.dumps(data), headers=aheaders, timeout=10)  # 第二次
                    if rp:
                        if rp.status_code == 200:
                            print('话单已推送=', data)
                        else:
                            time.sleep(10)
                            print('话单重推开始')
                            rp = requests.post(url, data=json.dumps(data), headers=aheaders, timeout=10)  # 第三次
                            if rp:
                                if rp.status_code == 200:
                                    print('话单已推送=', data)
                                else:
                                    fname = 'tuisongchaoshi***' + data['call_uuid']
                                    wcdr(fname, data)
        else:
            return 0

    except Exception as e:
        print("处理来电cdr错误:")
        print(e)
        print(traceback.format_exc())
        # 名称时间戳，写到log
        fname = str(time.time())
        wcdr(fname, ddj)
        return 0


'''
# cdr线程函数，处理话单推送
'''


class cdrThread(threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter

    def run(self):
        try:
            print("开始cdr处理线程：" + self.name)
            postcdr(self.counter)
            print("退出cdr事件线程：" + self.name)
        except Exception as e:
            print("事件cdr错误:")
            print(e)
            print(traceback.format_exc())


'''线程调用开始cdr'''


def cdrt(data):
    ran_str = random.randrange(1, 100000, 1)
    nowtime = datetime.now().strftime("%Y%m%d%H%M%S")
    ran = str(ran_str) + nowtime
    threadjkf = cdrThread(int(ran), ran, data)
    threadjkf.start()
    print('调用cdr处理进程开始：' + ran)
